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