source: branches/samba-3.0/source/rpc_server/srv_svcctl_nt.c@ 403

Last change on this file since 403 was 1, checked in by Paul Smedley, 19 years ago

Initial code import

File size: 25.5 KB
Line 
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
30struct 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 */
38extern SERVICE_CONTROL_OPS rcinit_svc_ops;
39
40/* builtin services (see service_db.c and services/svc_*.c */
41extern SERVICE_CONTROL_OPS spoolss_svc_ops;
42extern SERVICE_CONTROL_OPS netlogon_svc_ops;
43extern SERVICE_CONTROL_OPS winreg_svc_ops;
44extern 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
51struct service_control_op *svcctl_ops;
52
53static struct generic_mapping scm_generic_map =
54 { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };
55static struct generic_mapping svc_generic_map =
56 { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };
57
58
59/********************************************************************
60********************************************************************/
61
62BOOL 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
109static 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
123static 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
141static 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
176static 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
185static 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
200static 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
255done:
256 if ( !W_ERROR_IS_OK(result) )
257 free_service_handle_info( info );
258
259 return result;
260}
261
262/********************************************************************
263********************************************************************/
264
265WERROR _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
287WERROR _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
321WERROR _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
329WERROR _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
351WERROR _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
371static 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
404WERROR _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
460WERROR _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
478WERROR _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
509WERROR _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
537WERROR _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
588static 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" ) && ( lp_servicenumber(name) == -1 ) )
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
643WERROR _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
680WERROR _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
746WERROR _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
767WERROR _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
781WERROR _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
825WERROR _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
Note: See TracBrowser for help on using the repository browser.