r12914: adding query/set ops for security descriptors on services.
[amitay/samba.git] / source3 / rpc_server / srv_svcctl_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *
5  *  Copyright (C) Marcin Krzysztof Porwit           2005.
6  * 
7  *  Largely Rewritten (Again) by:
8  *  Copyright (C) Gerald (Jerry) Carter             2005.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_SRV
29
30 struct service_control_op {
31         const char *name;
32         SERVICE_CONTROL_OPS *ops;
33 };
34
35 #define SVCCTL_NUM_INTERNAL_SERVICES    4
36
37 /* handle external services */
38 extern SERVICE_CONTROL_OPS rcinit_svc_ops;
39
40 /* builtin services (see service_db.c and services/svc_*.c */
41 extern SERVICE_CONTROL_OPS spoolss_svc_ops;
42 extern SERVICE_CONTROL_OPS netlogon_svc_ops;
43 extern SERVICE_CONTROL_OPS winreg_svc_ops;
44 extern SERVICE_CONTROL_OPS wins_svc_ops;
45
46 /* make sure this number patches the number of builtin
47    SERVICE_CONTROL_OPS structure listed above */
48
49 #define SVCCTL_NUM_INTERNAL_SERVICES    4
50
51 struct service_control_op *svcctl_ops;
52
53 static struct generic_mapping scm_generic_map =
54         { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };
55 static struct generic_mapping svc_generic_map =
56         { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };
57
58
59 /********************************************************************
60 ********************************************************************/
61
62 BOOL init_service_op_table( void )
63 {
64         const char **service_list = lp_svcctl_list();
65         int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_count( service_list );
66         int i;
67         
68         if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) {
69                 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
70                 return False;
71         }
72
73         /* services listed in smb.conf get the rc.init interface */
74         
75         for ( i=0; service_list[i]; i++ ) {
76                 svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] );
77                 svcctl_ops[i].ops  = &rcinit_svc_ops;
78         }
79         
80         /* add builtin services */
81         
82         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
83         svcctl_ops[i].ops  = &spoolss_svc_ops;
84         i++;
85         
86         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
87         svcctl_ops[i].ops  = &netlogon_svc_ops;
88         i++;
89         
90         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
91         svcctl_ops[i].ops  = &winreg_svc_ops;
92         i++;
93         
94         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
95         svcctl_ops[i].ops  = &wins_svc_ops;
96         i++;
97         
98         /* NULL terminate the array */
99         
100         svcctl_ops[i].name = NULL;
101         svcctl_ops[i].ops  = NULL;
102         
103         return True;
104 }
105
106 /********************************************************************
107 ********************************************************************/
108
109 static struct service_control_op* find_service_by_name( const char *name )
110 {
111         int i;
112
113         for ( i=0; svcctl_ops[i].name; i++ ) {
114                 if ( strequal( name, svcctl_ops[i].name ) )
115                         return &svcctl_ops[i];
116         }
117
118         return NULL;
119 }
120 /********************************************************************
121 ********************************************************************/
122
123 static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, 
124                                      uint32 access_desired, uint32 *access_granted )
125 {
126         NTSTATUS result;
127
128         if ( geteuid() == sec_initial_uid() ) {
129                 DEBUG(5,("svcctl_access_check: using root's token\n"));
130                 token = get_root_nt_token();
131         }
132         
133         se_access_check( sec_desc, token, access_desired, access_granted, &result );
134
135         return result;
136 }
137
138 /********************************************************************
139 ********************************************************************/
140
141 static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
142 {
143         SEC_ACE ace[2]; 
144         SEC_ACCESS mask;
145         size_t i = 0;
146         SEC_DESC *sd;
147         SEC_ACL *acl;
148         size_t sd_size;
149
150         /* basic access for Everyone */
151         
152         init_sec_access(&mask, SC_MANAGER_READ_ACCESS );
153         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
154         
155         /* Full Access 'BUILTIN\Administrators' */
156         
157         init_sec_access(&mask,SC_MANAGER_ALL_ACCESS );
158         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
159         
160         
161         /* create the security descriptor */
162         
163         if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
164                 return NULL;
165
166         if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
167                 return NULL;
168
169         return sd;
170 }
171
172 /******************************************************************
173  free() function for REGISTRY_KEY
174  *****************************************************************/
175  
176 static void free_service_handle_info(void *ptr)
177 {
178         TALLOC_FREE( ptr );
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(pipes_struct *p, POLICY_HND *hnd)
186 {
187         SERVICE_INFO *service_info = NULL;
188
189         if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) {
190                 DEBUG(2,("find_service_info_by_hnd: handle not found"));
191                 return NULL;
192         }
193
194         return service_info;
195 }
196
197 /******************************************************************
198  *****************************************************************/
199  
200 static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, uint32 type,
201                                           const char *service, uint32 access_granted )
202 {
203         SERVICE_INFO *info = NULL;
204         WERROR result = WERR_OK;
205         struct service_control_op *s_op;
206         
207         if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) )
208                 return WERR_NOMEM;
209
210         /* the Service Manager has a NULL name */
211         
212         info->type = SVC_HANDLE_IS_SCM;
213         
214         switch ( type ) {
215         case SVC_HANDLE_IS_SCM:
216                 info->type = SVC_HANDLE_IS_SCM;
217                 break;
218
219         case SVC_HANDLE_IS_DBLOCK:
220                 info->type = SVC_HANDLE_IS_DBLOCK;
221                 break;
222                 
223         case SVC_HANDLE_IS_SERVICE:
224                 info->type = SVC_HANDLE_IS_SERVICE;
225                 
226                 /* lookup the SERVICE_CONTROL_OPS */
227
228                 if ( !(s_op = find_service_by_name( service )) ) {
229                         result = WERR_NO_SUCH_SERVICE;
230                         goto done;
231                 }
232                 
233                 info->ops = s_op->ops;
234
235                 if ( !(info->name  = talloc_strdup( info, s_op->name )) ) {
236                         result = WERR_NOMEM;
237                         goto done;
238                 }
239                 break;
240
241         default:
242                 result = WERR_NO_SUCH_SERVICE;
243                 goto done;
244         }
245
246         info->access_granted = access_granted;  
247         
248         /* store the SERVICE_INFO and create an open handle */
249         
250         if ( !create_policy_hnd( p, handle, free_service_handle_info, info ) ) {
251                 result = WERR_ACCESS_DENIED;
252                 goto done;
253         }
254                 
255 done:
256         if ( !W_ERROR_IS_OK(result) )
257                 free_service_handle_info( info );
258
259         return result;
260 }
261
262 /********************************************************************
263 ********************************************************************/
264
265 WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u)
266 {
267         SEC_DESC *sec_desc;
268         uint32 access_granted = 0;
269         NTSTATUS status;
270         
271         /* perform access checks */
272         
273         if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
274                 return WERR_NOMEM;
275                 
276         se_map_generic( &q_u->access, &scm_generic_map );
277         status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
278         if ( !NT_STATUS_IS_OK(status) )
279                 return ntstatus_to_werror( status );
280                 
281         return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
282 }
283
284 /********************************************************************
285 ********************************************************************/
286
287 WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u)
288 {
289         SEC_DESC *sec_desc;
290         uint32 access_granted = 0;
291         NTSTATUS status;
292         pstring service;
293
294         rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
295         
296         DEBUG(5, ("_svcctl_open_service: Attempting to open Service [%s], \n", service));
297
298         
299         /* based on my tests you can open a service if you have a valid scm handle */
300         
301         if ( !find_service_info_by_hnd( p, &q_u->handle ) )
302                 return WERR_BADFID;
303                         
304         /* perform access checks.  Use the root token in order to ensure that we 
305            retreive the security descriptor */
306         
307         if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) )
308                 return WERR_NOMEM;
309                 
310         se_map_generic( &q_u->access, &svc_generic_map );
311         status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
312         if ( !NT_STATUS_IS_OK(status) )
313                 return ntstatus_to_werror( status );
314         
315         return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
316 }
317
318 /********************************************************************
319 ********************************************************************/
320
321 WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u)
322 {
323         return close_policy_hnd( p, &q_u->handle ) ? WERR_OK : WERR_BADFID;
324 }
325
326 /********************************************************************
327 ********************************************************************/
328
329 WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u)
330 {
331         fstring service;
332         const char *display_name;
333         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
334         
335         /* can only use an SCM handle here */
336         
337         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
338                 return WERR_BADFID;
339                 
340         rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
341         
342         display_name = svcctl_lookup_dispname( service, p->pipe_user.nt_user_token );
343         init_svcctl_r_get_display_name( r_u, display_name );
344
345         return WERR_OK;
346 }
347
348 /********************************************************************
349 ********************************************************************/
350
351 WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u)
352 {
353         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
354         
355         /* perform access checks */
356
357         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
358                 return WERR_BADFID;
359                 
360         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
361                 return WERR_ACCESS_DENIED;
362                 
363         /* try the service specific status call */
364
365         return info->ops->service_status( info->name, &r_u->svc_status );
366 }
367
368 /********************************************************************
369 ********************************************************************/
370
371 static int enumerate_status( TALLOC_CTX *ctx, ENUM_SERVICES_STATUS **status, NT_USER_TOKEN *token )
372 {
373         int num_services = 0;
374         int i;
375         ENUM_SERVICES_STATUS *st;
376         const char *display_name;
377         
378         /* just count */
379         while ( svcctl_ops[num_services].name )
380                 num_services++;
381
382         if ( !(st = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) ) {
383                 DEBUG(0,("enumerate_status: talloc() failed!\n"));
384                 return -1;
385         }
386         
387         for ( i=0; i<num_services; i++ ) {
388                 init_unistr( &st[i].servicename, svcctl_ops[i].name );
389                 
390                 display_name = svcctl_lookup_dispname( svcctl_ops[i].name, token );
391                 init_unistr( &st[i].displayname, display_name );
392                 
393                 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
394         }
395         
396         *status = st;
397
398         return num_services;
399 }
400
401 /********************************************************************
402 ********************************************************************/
403
404 WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
405 {
406         ENUM_SERVICES_STATUS *services = NULL;
407         uint32 num_services;
408         int i = 0;
409         size_t buffer_size = 0;
410         WERROR result = WERR_OK;
411         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
412         NT_USER_TOKEN *token = p->pipe_user.nt_user_token;
413         
414         /* perform access checks */
415
416         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
417                 return WERR_BADFID;
418                 
419         if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) )
420                 return WERR_ACCESS_DENIED;
421
422         if ( (num_services = enumerate_status( p->mem_ctx, &services, token )) == -1 )
423                 return WERR_NOMEM;
424
425         for ( i=0; i<num_services; i++ ) {
426                 buffer_size += svcctl_sizeof_enum_services_status(&services[i]);
427         }
428
429         buffer_size += buffer_size % 4;
430
431         if (buffer_size > q_u->buffer_size ) {
432                 num_services = 0;
433                 result = WERR_MORE_DATA;
434         }
435
436         rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx);
437
438         if ( W_ERROR_IS_OK(result) ) {
439                 for ( i=0; i<num_services; i++ )
440                         svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
441         }
442
443         r_u->needed      = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
444         r_u->returned    = num_services;
445
446         if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
447                 return WERR_NOMEM;
448
449         *r_u->resume = 0x0;
450
451         return result;
452 }
453
454 /********************************************************************
455 ********************************************************************/
456
457 WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u)
458 {
459         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
460         
461         /* perform access checks */
462
463         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
464                 return WERR_BADFID;
465         
466         if ( !(info->access_granted & SC_RIGHT_SVC_START) )
467                 return WERR_ACCESS_DENIED;
468                 
469         return info->ops->start_service( info->name );
470 }
471
472 /********************************************************************
473 ********************************************************************/
474
475 WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u)
476 {
477         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
478         
479         /* perform access checks */
480         
481         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
482                 return WERR_BADFID;     
483         
484         switch ( q_u->control ) {
485         case SVCCTL_CONTROL_STOP:
486                 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
487                         return WERR_ACCESS_DENIED;
488                         
489                 return info->ops->stop_service( info->name, &r_u->svc_status );
490                 
491         case SVCCTL_CONTROL_INTERROGATE:
492                 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
493                         return WERR_ACCESS_DENIED;
494                         
495                 return info->ops->service_status( info->name, &r_u->svc_status );
496         }
497         
498         /* default control action */
499         
500         return WERR_ACCESS_DENIED;
501 }
502
503 /********************************************************************
504 ********************************************************************/
505
506 WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u )
507 {
508         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
509         
510         /* perform access checks */
511
512         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
513                 return WERR_BADFID;     
514         
515         if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
516                 return WERR_ACCESS_DENIED;
517                         
518         /* we have to set the outgoing buffer size to the same as the 
519            incoming buffer size (even in the case of failure */
520
521         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
522                                 
523         r_u->needed      = q_u->buffer_size;
524         
525         /* no dependent services...basically a stub function */
526         r_u->returned    = 0;
527
528         return WERR_OK;
529 }
530
531 /********************************************************************
532 ********************************************************************/
533
534 WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_STATUSEX *q_u, SVCCTL_R_QUERY_SERVICE_STATUSEX *r_u )
535 {
536         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
537         uint32 buffer_size;
538         
539         /* perform access checks */
540
541         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
542                 return WERR_BADFID;     
543         
544         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
545                 return WERR_ACCESS_DENIED;
546
547         /* we have to set the outgoing buffer size to the same as the 
548            incoming buffer size (even in the case of failure) */
549
550         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
551         r_u->needed = q_u->buffer_size;
552         
553         switch ( q_u->level ) {
554                 case SVC_STATUS_PROCESS_INFO:
555                 {
556                         SERVICE_STATUS_PROCESS svc_stat_proc;
557
558                         /* Get the status of the service.. */
559                         info->ops->service_status( info->name, &svc_stat_proc.status );
560                         svc_stat_proc.process_id     = sys_getpid();
561                         svc_stat_proc.service_flags  = 0x0;
562
563                         svcctl_io_service_status_process( "", &svc_stat_proc, &r_u->buffer, 0 );
564                         buffer_size = sizeof(SERVICE_STATUS_PROCESS);
565                         break;
566                 }
567                         
568                 default:
569                         return WERR_UNKNOWN_LEVEL; 
570         }
571
572         
573         buffer_size += buffer_size % 4;
574         r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
575
576         if (buffer_size > q_u->buffer_size ) 
577                 return WERR_MORE_DATA;
578         
579         return WERR_OK;
580 }
581
582 /********************************************************************
583 ********************************************************************/
584
585 static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG *config, NT_USER_TOKEN *token )
586 {
587         REGVAL_CTR *values;
588         REGISTRY_VALUE *val;
589
590         /* retrieve the registry values for this service */
591         
592         if ( !(values = svcctl_fetch_regvalues( name, token )) )
593                 return WERR_REG_CORRUPT;
594         
595         /* now fill in the individual values */
596                 
597         config->displayname = TALLOC_ZERO_P( ctx, UNISTR2 );
598         if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL )
599                 init_unistr2( config->displayname, regval_sz( val ), UNI_STR_TERMINATE );
600         else
601                 init_unistr2( config->displayname, name, UNI_STR_TERMINATE );
602
603         if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) {
604                 config->startname = TALLOC_ZERO_P( ctx, UNISTR2 );              
605                 init_unistr2( config->startname, regval_sz( val ), UNI_STR_TERMINATE );
606         }
607                 
608         if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) {
609                 config->executablepath = TALLOC_ZERO_P( ctx, UNISTR2 );         
610                 init_unistr2( config->executablepath, regval_sz( val ), UNI_STR_TERMINATE );
611         }
612
613         /* a few hard coded values */
614         /* loadordergroup and dependencies are empty */
615         
616         config->tag_id           = 0x00000000;                  /* unassigned loadorder group */
617         config->service_type     = SVCCTL_WIN32_OWN_PROC;
618         config->error_control    = SVCCTL_SVC_ERROR_NORMAL;
619
620         /* set the start type.  NetLogon and WINS are disabled to prevent 
621            the client from showing the "Start" button (if of course the services
622            are not running */
623
624         if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
625                 config->start_type = SVCCTL_DISABLED;
626         else if ( strequal( name, "WINS" ) && ( !lp_wins_support() ))
627                 config->start_type = SVCCTL_DISABLED;
628         else
629                 config->start_type = SVCCTL_DEMAND_START;
630         
631
632         TALLOC_FREE( values );
633
634         return WERR_OK;
635 }
636
637 /********************************************************************
638 ********************************************************************/
639
640 WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
641 {
642         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
643         uint32 buffer_size;
644         WERROR wresult;
645         
646         /* perform access checks */
647
648         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
649                 return WERR_BADFID;     
650         
651         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
652                 return WERR_ACCESS_DENIED;
653
654         /* we have to set the outgoing buffer size to the same as the 
655            incoming buffer size (even in the case of failure */
656
657         r_u->needed      = q_u->buffer_size;
658         
659         wresult = fill_svc_config( p->mem_ctx, info->name, &r_u->config, p->pipe_user.nt_user_token );
660         if ( !W_ERROR_IS_OK(wresult) )
661                 return wresult;
662         
663         buffer_size = svcctl_sizeof_service_config( &r_u->config );
664         r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
665
666         if (buffer_size > q_u->buffer_size ) {
667                 ZERO_STRUCTP( &r_u->config );
668                 return WERR_INSUFFICIENT_BUFFER;
669         }
670                 
671         return WERR_OK;
672 }
673
674 /********************************************************************
675 ********************************************************************/
676
677 WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG2 *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u )
678 {
679         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
680         uint32 buffer_size;
681         
682         /* perform access checks */
683
684         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
685                 return WERR_BADFID;     
686         
687         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
688                 return WERR_ACCESS_DENIED;
689  
690         /* we have to set the outgoing buffer size to the same as the 
691            incoming buffer size (even in the case of failure */
692
693         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
694         r_u->needed = q_u->buffer_size;
695
696         switch ( q_u->level ) {
697         case SERVICE_CONFIG_DESCRIPTION:
698                 {
699                         SERVICE_DESCRIPTION desc_buf;
700                         const char *description;
701                         
702                         description = svcctl_lookup_description( info->name, p->pipe_user.nt_user_token );
703                         
704                         ZERO_STRUCTP( &desc_buf );
705
706                         init_service_description_buffer( &desc_buf, description );
707                         svcctl_io_service_description( "", &desc_buf, &r_u->buffer, 0 );
708                         buffer_size = svcctl_sizeof_service_description( &desc_buf );
709
710                         break;
711                 }
712                 break;
713         case SERVICE_CONFIG_FAILURE_ACTIONS:
714                 {
715                         SERVICE_FAILURE_ACTIONS actions;
716
717                         /* nothing to say...just service the request */
718
719                         ZERO_STRUCTP( &actions );
720                         svcctl_io_service_fa( "", &actions, &r_u->buffer, 0 );
721                         buffer_size = svcctl_sizeof_service_fa( &actions );
722
723                         break;
724                 }
725                 break;
726
727         default:
728                 return WERR_UNKNOWN_LEVEL;
729         }
730         
731         buffer_size += buffer_size % 4;
732         r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
733
734         if (buffer_size > q_u->buffer_size )
735                 return WERR_INSUFFICIENT_BUFFER;
736
737         return WERR_OK;
738 }
739
740 /********************************************************************
741 ********************************************************************/
742
743 WERROR _svcctl_lock_service_db( pipes_struct *p, SVCCTL_Q_LOCK_SERVICE_DB *q_u, SVCCTL_R_LOCK_SERVICE_DB *r_u )
744 {
745         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
746         
747         /* perform access checks */
748
749         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
750                 return WERR_BADFID;     
751         
752         if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
753                 return WERR_ACCESS_DENIED;
754
755         /* Just open a handle.  Doesn't actually lock anything */
756         
757         return create_open_service_handle( p, &r_u->h_lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
758 ;
759 }
760
761 /********************************************************************
762 ********************************************************************/
763
764 WERROR _svcctl_unlock_service_db( pipes_struct *p, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, SVCCTL_R_UNLOCK_SERVICE_DB *r_u )
765 {
766         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->h_lock );
767
768
769         if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
770                 return WERR_BADFID;     
771                 
772         return close_policy_hnd( p, &q_u->h_lock) ? WERR_OK : WERR_BADFID;
773 }
774
775 /********************************************************************
776 ********************************************************************/
777
778 WERROR _svcctl_query_service_sec( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_SEC *q_u, SVCCTL_R_QUERY_SERVICE_SEC *r_u )
779 {
780         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
781         SEC_DESC *sec_desc;
782
783
784         /* only support the SCM and individual services */
785
786         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
787                 return WERR_BADFID;     
788
789         /* check access reights (according to MSDN) */
790
791         if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
792                 return WERR_ACCESS_DENIED;
793
794         /* TODO: handle something besides DACL_SECURITY_INFORMATION */
795
796         if ( (q_u->security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION )
797                 return WERR_INVALID_PARAM;
798
799         /* lookup the security descriptor and marshall it up for a reply */
800
801         if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) )
802                 return WERR_NOMEM;
803
804         r_u->needed = sec_desc_size( sec_desc );
805
806         if ( r_u->needed > q_u->buffer_size ) {
807                 ZERO_STRUCTP( &r_u->buffer );
808                 return WERR_INSUFFICIENT_BUFFER;
809         }
810
811         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
812
813         if ( !sec_io_desc("", &sec_desc, &r_u->buffer.prs, 0 ) )
814                 return WERR_NOMEM;
815                 
816         return WERR_OK;
817 }
818
819 /********************************************************************
820 ********************************************************************/
821
822 WERROR _svcctl_set_service_sec( pipes_struct *p, SVCCTL_Q_SET_SERVICE_SEC *q_u, SVCCTL_R_SET_SERVICE_SEC *r_u )
823 {
824         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
825         SEC_DESC *sec_desc = NULL;
826         uint32 required_access;
827
828         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM))  )
829                 return WERR_BADFID;
830
831         /* check the access on the open handle */
832         
833         switch ( q_u->security_flags ) {
834                 case DACL_SECURITY_INFORMATION:
835                         required_access = STD_RIGHT_WRITE_DAC_ACCESS;
836                         break;
837                         
838                 case OWNER_SECURITY_INFORMATION:
839                 case GROUP_SECURITY_INFORMATION:
840                         required_access = STD_RIGHT_WRITE_OWNER_ACCESS;
841                         break;
842                         
843                 case SACL_SECURITY_INFORMATION:
844                         return WERR_INVALID_PARAM;
845                 default:
846                         return WERR_INVALID_PARAM;
847         }
848         
849         if ( !(info->access_granted & required_access) )
850                 return WERR_ACCESS_DENIED;
851         
852         /* read the security descfriptor */
853                 
854         if ( !sec_io_desc("", &sec_desc, &q_u->buffer.prs, 0 ) )
855                 return WERR_NOMEM;
856                 
857         /* store the new SD */
858
859         if ( !svcctl_set_secdesc( p->mem_ctx, info->name, sec_desc, p->pipe_user.nt_user_token ) ) 
860                 return WERR_ACCESS_DENIED;
861
862         return WERR_OK;
863 }
864
865