r23055: Rewrite messages.c to use auto-generated marshalling in the tdb. I'm
[tprouty/samba.git] / source / 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 && 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            retrieve 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         int 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
423         num_services = enumerate_status( p->mem_ctx, &services, token );
424         if (num_services == -1 ) {
425                 return WERR_NOMEM;
426         }
427
428         for ( i=0; i<num_services; i++ ) {
429                 buffer_size += svcctl_sizeof_enum_services_status(&services[i]);
430         }
431
432         buffer_size += buffer_size % 4;
433
434         if (buffer_size > q_u->buffer_size ) {
435                 num_services = 0;
436                 result = WERR_MORE_DATA;
437         }
438
439         rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx);
440
441         if ( W_ERROR_IS_OK(result) ) {
442                 for ( i=0; i<num_services; i++ )
443                         svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
444         }
445
446         r_u->needed      = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
447         r_u->returned    = (uint32)num_services;
448
449         if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
450                 return WERR_NOMEM;
451
452         *r_u->resume = 0x0;
453
454         return result;
455 }
456
457 /********************************************************************
458 ********************************************************************/
459
460 WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u)
461 {
462         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
463         
464         /* perform access checks */
465
466         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
467                 return WERR_BADFID;
468         
469         if ( !(info->access_granted & SC_RIGHT_SVC_START) )
470                 return WERR_ACCESS_DENIED;
471                 
472         return info->ops->start_service( info->name );
473 }
474
475 /********************************************************************
476 ********************************************************************/
477
478 WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u)
479 {
480         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
481         
482         /* perform access checks */
483         
484         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
485                 return WERR_BADFID;     
486         
487         switch ( q_u->control ) {
488         case SVCCTL_CONTROL_STOP:
489                 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
490                         return WERR_ACCESS_DENIED;
491                         
492                 return info->ops->stop_service( info->name, &r_u->svc_status );
493                 
494         case SVCCTL_CONTROL_INTERROGATE:
495                 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
496                         return WERR_ACCESS_DENIED;
497                         
498                 return info->ops->service_status( info->name, &r_u->svc_status );
499         }
500         
501         /* default control action */
502         
503         return WERR_ACCESS_DENIED;
504 }
505
506 /********************************************************************
507 ********************************************************************/
508
509 WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u )
510 {
511         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
512         
513         /* perform access checks */
514
515         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
516                 return WERR_BADFID;     
517         
518         if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
519                 return WERR_ACCESS_DENIED;
520                         
521         /* we have to set the outgoing buffer size to the same as the 
522            incoming buffer size (even in the case of failure */
523
524         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
525                                 
526         r_u->needed      = q_u->buffer_size;
527         
528         /* no dependent services...basically a stub function */
529         r_u->returned    = 0;
530
531         return WERR_OK;
532 }
533
534 /********************************************************************
535 ********************************************************************/
536
537 WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_STATUSEX *q_u, SVCCTL_R_QUERY_SERVICE_STATUSEX *r_u )
538 {
539         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
540         uint32 buffer_size;
541         
542         /* perform access checks */
543
544         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
545                 return WERR_BADFID;     
546         
547         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
548                 return WERR_ACCESS_DENIED;
549
550         /* we have to set the outgoing buffer size to the same as the 
551            incoming buffer size (even in the case of failure) */
552
553         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
554         r_u->needed = q_u->buffer_size;
555         
556         switch ( q_u->level ) {
557                 case SVC_STATUS_PROCESS_INFO:
558                 {
559                         SERVICE_STATUS_PROCESS svc_stat_proc;
560
561                         /* Get the status of the service.. */
562                         info->ops->service_status( info->name, &svc_stat_proc.status );
563                         svc_stat_proc.process_id     = sys_getpid();
564                         svc_stat_proc.service_flags  = 0x0;
565
566                         svcctl_io_service_status_process( "", &svc_stat_proc, &r_u->buffer, 0 );
567                         buffer_size = sizeof(SERVICE_STATUS_PROCESS);
568                         break;
569                 }
570                         
571                 default:
572                         return WERR_UNKNOWN_LEVEL; 
573         }
574
575         
576         buffer_size += buffer_size % 4;
577         r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
578
579         if (buffer_size > q_u->buffer_size ) 
580                 return WERR_MORE_DATA;
581         
582         return WERR_OK;
583 }
584
585 /********************************************************************
586 ********************************************************************/
587
588 static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG *config, NT_USER_TOKEN *token )
589 {
590         REGVAL_CTR *values;
591         REGISTRY_VALUE *val;
592
593         /* retrieve the registry values for this service */
594         
595         if ( !(values = svcctl_fetch_regvalues( name, token )) )
596                 return WERR_REG_CORRUPT;
597         
598         /* now fill in the individual values */
599                 
600         config->displayname = TALLOC_ZERO_P( ctx, UNISTR2 );
601         if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL )
602                 init_unistr2( config->displayname, regval_sz( val ), UNI_STR_TERMINATE );
603         else
604                 init_unistr2( config->displayname, name, UNI_STR_TERMINATE );
605
606         if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) {
607                 config->startname = TALLOC_ZERO_P( ctx, UNISTR2 );              
608                 init_unistr2( config->startname, regval_sz( val ), UNI_STR_TERMINATE );
609         }
610                 
611         if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) {
612                 config->executablepath = TALLOC_ZERO_P( ctx, UNISTR2 );         
613                 init_unistr2( config->executablepath, regval_sz( val ), UNI_STR_TERMINATE );
614         }
615
616         /* a few hard coded values */
617         /* loadordergroup and dependencies are empty */
618         
619         config->tag_id           = 0x00000000;                  /* unassigned loadorder group */
620         config->service_type     = SVCCTL_WIN32_OWN_PROC;
621         config->error_control    = SVCCTL_SVC_ERROR_NORMAL;
622
623         /* set the start type.  NetLogon and WINS are disabled to prevent 
624            the client from showing the "Start" button (if of course the services
625            are not running */
626
627         if ( strequal( name, "NETLOGON" ) && ( !share_defined(name) ) )
628                 config->start_type = SVCCTL_DISABLED;
629         else if ( strequal( name, "WINS" ) && ( !lp_wins_support() ))
630                 config->start_type = SVCCTL_DISABLED;
631         else
632                 config->start_type = SVCCTL_DEMAND_START;
633         
634
635         TALLOC_FREE( values );
636
637         return WERR_OK;
638 }
639
640 /********************************************************************
641 ********************************************************************/
642
643 WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
644 {
645         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
646         uint32 buffer_size;
647         WERROR wresult;
648         
649         /* perform access checks */
650
651         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
652                 return WERR_BADFID;     
653         
654         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
655                 return WERR_ACCESS_DENIED;
656
657         /* we have to set the outgoing buffer size to the same as the 
658            incoming buffer size (even in the case of failure */
659
660         r_u->needed      = q_u->buffer_size;
661         
662         wresult = fill_svc_config( p->mem_ctx, info->name, &r_u->config, p->pipe_user.nt_user_token );
663         if ( !W_ERROR_IS_OK(wresult) )
664                 return wresult;
665         
666         buffer_size = svcctl_sizeof_service_config( &r_u->config );
667         r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
668
669         if (buffer_size > q_u->buffer_size ) {
670                 ZERO_STRUCTP( &r_u->config );
671                 return WERR_INSUFFICIENT_BUFFER;
672         }
673                 
674         return WERR_OK;
675 }
676
677 /********************************************************************
678 ********************************************************************/
679
680 WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG2 *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u )
681 {
682         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
683         uint32 buffer_size;
684         
685         /* perform access checks */
686
687         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
688                 return WERR_BADFID;     
689         
690         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
691                 return WERR_ACCESS_DENIED;
692  
693         /* we have to set the outgoing buffer size to the same as the 
694            incoming buffer size (even in the case of failure */
695
696         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
697         r_u->needed = q_u->buffer_size;
698
699         switch ( q_u->level ) {
700         case SERVICE_CONFIG_DESCRIPTION:
701                 {
702                         SERVICE_DESCRIPTION desc_buf;
703                         const char *description;
704                         
705                         description = svcctl_lookup_description( info->name, p->pipe_user.nt_user_token );
706                         
707                         ZERO_STRUCTP( &desc_buf );
708
709                         init_service_description_buffer( &desc_buf, description );
710                         svcctl_io_service_description( "", &desc_buf, &r_u->buffer, 0 );
711                         buffer_size = svcctl_sizeof_service_description( &desc_buf );
712
713                         break;
714                 }
715                 break;
716         case SERVICE_CONFIG_FAILURE_ACTIONS:
717                 {
718                         SERVICE_FAILURE_ACTIONS actions;
719
720                         /* nothing to say...just service the request */
721
722                         ZERO_STRUCTP( &actions );
723                         svcctl_io_service_fa( "", &actions, &r_u->buffer, 0 );
724                         buffer_size = svcctl_sizeof_service_fa( &actions );
725
726                         break;
727                 }
728                 break;
729
730         default:
731                 return WERR_UNKNOWN_LEVEL;
732         }
733         
734         buffer_size += buffer_size % 4;
735         r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
736
737         if (buffer_size > q_u->buffer_size )
738                 return WERR_INSUFFICIENT_BUFFER;
739
740         return WERR_OK;
741 }
742
743 /********************************************************************
744 ********************************************************************/
745
746 WERROR _svcctl_lock_service_db( pipes_struct *p, SVCCTL_Q_LOCK_SERVICE_DB *q_u, SVCCTL_R_LOCK_SERVICE_DB *r_u )
747 {
748         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
749         
750         /* perform access checks */
751
752         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
753                 return WERR_BADFID;     
754         
755         if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
756                 return WERR_ACCESS_DENIED;
757
758         /* Just open a handle.  Doesn't actually lock anything */
759         
760         return create_open_service_handle( p, &r_u->h_lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
761 ;
762 }
763
764 /********************************************************************
765 ********************************************************************/
766
767 WERROR _svcctl_unlock_service_db( pipes_struct *p, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, SVCCTL_R_UNLOCK_SERVICE_DB *r_u )
768 {
769         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->h_lock );
770
771
772         if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
773                 return WERR_BADFID;     
774                 
775         return close_policy_hnd( p, &q_u->h_lock) ? WERR_OK : WERR_BADFID;
776 }
777
778 /********************************************************************
779 ********************************************************************/
780
781 WERROR _svcctl_query_service_sec( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_SEC *q_u, SVCCTL_R_QUERY_SERVICE_SEC *r_u )
782 {
783         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
784         SEC_DESC *sec_desc;
785
786
787         /* only support the SCM and individual services */
788
789         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
790                 return WERR_BADFID;     
791
792         /* check access reights (according to MSDN) */
793
794         if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
795                 return WERR_ACCESS_DENIED;
796
797         /* TODO: handle something besides DACL_SECURITY_INFORMATION */
798
799         if ( (q_u->security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION )
800                 return WERR_INVALID_PARAM;
801
802         /* lookup the security descriptor and marshall it up for a reply */
803
804         if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) )
805                 return WERR_NOMEM;
806
807         r_u->needed = sec_desc_size( sec_desc );
808
809         if ( r_u->needed > q_u->buffer_size ) {
810                 ZERO_STRUCTP( &r_u->buffer );
811                 return WERR_INSUFFICIENT_BUFFER;
812         }
813
814         rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
815
816         if ( !sec_io_desc("", &sec_desc, &r_u->buffer.prs, 0 ) )
817                 return WERR_NOMEM;
818                 
819         return WERR_OK;
820 }
821
822 /********************************************************************
823 ********************************************************************/
824
825 WERROR _svcctl_set_service_sec( pipes_struct *p, SVCCTL_Q_SET_SERVICE_SEC *q_u, SVCCTL_R_SET_SERVICE_SEC *r_u )
826 {
827         SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
828         SEC_DESC *sec_desc = NULL;
829         uint32 required_access;
830
831         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM))  )
832                 return WERR_BADFID;
833
834         /* can't set the security de4scriptor on the ServiceControlManager */
835
836         if ( info->type == SVC_HANDLE_IS_SCM )
837                 return WERR_ACCESS_DENIED;      
838
839         /* check the access on the open handle */
840         
841         switch ( q_u->security_flags ) {
842                 case DACL_SECURITY_INFORMATION:
843                         required_access = STD_RIGHT_WRITE_DAC_ACCESS;
844                         break;
845                         
846                 case OWNER_SECURITY_INFORMATION:
847                 case GROUP_SECURITY_INFORMATION:
848                         required_access = STD_RIGHT_WRITE_OWNER_ACCESS;
849                         break;
850                         
851                 case SACL_SECURITY_INFORMATION:
852                         return WERR_INVALID_PARAM;
853                 default:
854                         return WERR_INVALID_PARAM;
855         }
856         
857         if ( !(info->access_granted & required_access) )
858                 return WERR_ACCESS_DENIED;
859         
860         /* read the security descfriptor */
861                 
862         if ( !sec_io_desc("", &sec_desc, &q_u->buffer.prs, 0 ) )
863                 return WERR_NOMEM;
864                 
865         /* store the new SD */
866
867         if ( !svcctl_set_secdesc( p->mem_ctx, info->name, sec_desc, p->pipe_user.nt_user_token ) ) 
868                 return WERR_ACCESS_DENIED;
869
870         return WERR_OK;
871 }
872
873